/*The windows header for all the windows functions*/
#include <windows.h>
#define VC_EXTRALEAN

/*All the classes we are including into the Main Entry Point*/
#include "Framework.h"

//////////////////////////////////////////////////////////////////////////////////////
/*Global Variables*/
//////////////////////////////////////////////////////////////////////////////////////

/*The handle to our window*/
HWND g_hWnd;			

/*The handle to the instance of our window*/
HINSTANCE g_hInstance;

/*The global variable to control whether we want windowed or full screen mode*/
bool g_bWindowed;

/*The screen Width and the screen Height*/
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

/*The title, the L in front of the screen is for unicode*/
#define WINDOW_TITLE L"Renderer"

/*The instance of our game class*/
Framework g_dxGame;

/*Our Main Entry Point function, This will create and run our game*/
int WINAPI wWinMain(HINSTANCE hInstance,
					HINSTANCE hPrevInstance,
					LPTSTR lpCmdLine,
					int lpCmdShow);

/*Window's procedure to handle messages*/
LRESULT CALLBACK WndProc(HWND hWnd,
						 UINT message,
						 WPARAM wparam,
						 LPARAM lparam);

/*The function we are using to initialize our window*/
void InitWindow()
{
	/*Create an object of the class we want*/
	WNDCLASSEX wndClass;

	/*Make sure to make all of the data within our class 0*/
	ZeroMemory(&wndClass, sizeof(WNDCLASSEX));

	/*The size of our window*/
	wndClass.cbSize			= sizeof(WNDCLASSEX);

	/*The Window procedure that we are going to be using for our window*/
	wndClass.lpfnWndProc	= (WNDPROC)WndProc;

	/*The name of the class that this window will have*/
	wndClass.lpszClassName	= WINDOW_TITLE;

	/*The handle to the instance we are creating*/
	wndClass.hInstance		= g_hInstance;

	/*The cursor we want to work with our window*/
	wndClass.hCursor		= LoadCursor(NULL, IDC_ARROW);

	/*The handle to the brush we want for our background*/
	wndClass.hbrBackground	= (HBRUSH)(COLOR_WINDOWFRAME);

	/*Register a new type of window so that it looks the way we want it to*/
	RegisterClassEx(&wndClass);

	/*Create our window and store the handle to the window in our global instance*/
	g_hWnd = CreateWindow(
		WINDOW_TITLE, WINDOW_TITLE,													//Window class name and title
		g_bWindowed ? WS_OVERLAPPEDWINDOW | WS_VISIBLE : (WS_POPUP | WS_VISIBLE),	//window style
		CW_USEDEFAULT, CW_USEDEFAULT,												//Window position (x,y)
		SCREEN_WIDTH, SCREEN_HEIGHT,												//window width/height
		NULL, NULL,																	//Parent Window and Menu Strip
		g_hInstance,																//Handle to the instance
		NULL);																		//LParam argument

	/*Display the window*/
	ShowWindow(g_hWnd, SW_SHOW);

	/*Update all of the things within the window for the moment*/
	UpdateWindow(g_hWnd);
}

/*Our Main Entry Point function, This will create and run our game*/
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	/*Sets the global instance for our handle to the window*/
	g_hInstance = hInstance;

	/*Makes the fact that we want to start the game in windowed mode true*/
	g_bWindowed = true;

	/*Initialize and create the window we will be using*/
	InitWindow();

	/*Use the MSG structure to catch windows messages*/
	MSG msg;

	/*Make sure to clear out the window message structure so we don't get a random message*/
	ZeroMemory(&msg, sizeof(MSG));

	/*Game Initialization, Create our game objects and all of the things that go with it*/
	g_dxGame.Initialize(g_hWnd, g_hInstance, g_bWindowed);


	/*Our loop to continuously run the game, We kick out when the message is QUIT*/
	while(msg.message != WM_QUIT)
	{
		/*Look into the message that we have, and remove it from the stack*/
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			/*Translate the message into something we can use*/
			TranslateMessage(&msg);

			/*Dispatch the message to the corresponding message procedure*/
			DispatchMessage(&msg);
		}

		/*Check to see if nothing has happened that could potentially have us lose our device*/
		if(!g_dxGame.lostDevice())
		{
			/*Game Update, move all of the objects, and do all of the calculations*/
			g_dxGame.Update();
			
			/*Game render, after all of the movements and translations render*/
			g_dxGame.Render();
		}
	}

	/*Game Shutdown, release all of the COM objects to reduce memory leaks*/
	g_dxGame.Shutdown();

	/*Unregister the window*/
	UnregisterClass(WINDOW_TITLE, g_hInstance);

	/*Exit the application, We have shutdown*/
	return 0;
}

/*Window's procedure to handle messages*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	/*This procedure will attempt to handle the messages we want*/
	switch(message)
	{
		/*If we are repainting the window*/
		case (WM_PAINT):
		{
			/*Make the entire window in*/
			InvalidateRect(hWnd, NULL, TRUE);
			break;
		}
		/*If we are done ReSizing the window*/
		case (WM_EXITSIZEMOVE):
		{
			/*Make sure we look if we have lost our device and do the things necessary so that we 
			don't crash*/
			g_dxGame.screenResize();
			break;
		}
		/*If the message is that we are going to destroy the window*/
		case (WM_DESTROY):
		{
			/*Post the quit message so we can close out of the loop[*/
			PostQuitMessage(0);
			break;
		}
	}

	/*If the message is one that we aren't trying to handle send it to the default window procedure*/
	return DefWindowProc(hWnd, message, wparam, lparam);
}